# app.py - FastAPI Service for Floral Art RAG System
import os
import base64
import json
import logging
import time
import base64
import uuid
import asyncio
from fastapi.staticfiles import StaticFiles
import requests
import re
from typing import Dict, Any, List, Optional, Union, Tuple
from fastapi import FastAPI, HTTPException, BackgroundTasks, Form, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException, BackgroundTasks, Form, File, UploadFile, Request
from fastapi.responses import JSONResponse
# Import our RAG system
from floral_rag import FloralArtApp, FloralRAGSystem
# 改为

from enhanced_image_generation import (
    AdvancedImageGenerator, InteractiveImageEditor,
    ImageGenerationRequest, ImageEditRequest,
    enhanced_generator, interactive_editor
)
# Import speech interaction module (现在使用百度API)
from speech_interaction import (
    speech_manager,
    SpeechRecognitionRequest,
    SpeechSynthesisRequest,
    DialectDetectionRequest,
    SUPPORTED_DIALECTS
)

# Import text-to-video module
from text2video import TextToVideoGenerator, TextToVideoRequest

# Load environment variables
load_dotenv()
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
TEXT_TO_IMAGE_API_KEY = os.getenv("TEXT_TO_IMAGE_API_KEY", "sk-6681c4a50d444dee8a8a17f3b2ef9913")

# 百度语音服务配置
BAIDU_APP_ID = os.getenv("BAIDU_APP_ID")
BAIDU_API_KEY = os.getenv("BAIDU_API_KEY")
BAIDU_SECRET_KEY = os.getenv("BAIDU_SECRET_KEY")

# Set up logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Initialize the Floral Art application
floral_app = FloralArtApp()


# Initialize text-to-video generator
video_generator = TextToVideoGenerator(floral_app.rag_system)

# Create directories for text-to-video outputs
os.makedirs("static/videos", exist_ok=True)
os.makedirs("static/images", exist_ok=True)
os.makedirs("static/audio", exist_ok=True)
os.makedirs("static/temp", exist_ok=True)
os.makedirs("static/tasks", exist_ok=True)

# FastAPI app
app = FastAPI(
    title="Floral Art AI API",
    description="API for floral arrangement knowledge and design using RAG and DeepSeek API (with Baidu Speech)",
    version="1.0.0"
)
# 服务静态文件
app.mount("/static", StaticFiles(directory="static"), name="static")
# Enable CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # In production, specify actual origins
    allow_methods=["*"],
    allow_headers=["*"],
)


# Request and response models (保持不变)
class QueryRequest(BaseModel):
    query: str
    generate_image: bool = False


class UploadRequest(BaseModel):
    file_path: str
    file_name: str


class QueryResponse(BaseModel):
    response: str
    source: str  # "local" or "rag+api"
    image_url: Optional[str] = None
    audio_response: Optional[str] = None  # Base64 encoded audio response




class AudioTranscriptRequest(BaseModel):
    audio_base64: str
    dialect: Optional[str] = "mandarin"


class SpeechQueryRequest(BaseModel):
    audio_base64: str
    dialect: Optional[str] = "mandarin"
    generate_image: bool = False
    voice_response: bool = True
    voice_id: Optional[str] = None


class AvailableVoicesResponse(BaseModel):
    voices: Dict[str, List[str]]


# Text-to-Video Models (保持不变)
class CreateVideoRequest(BaseModel):
    topic: str
    character_style: str = "anime"
    voice_id: Optional[str] = None
    style: str = "detailed"
    duration: int = 60
    language: str = "mandarin"


class VideoTaskResponse(BaseModel):
    task_id: str
    status: str
    message: str
    request: Dict[str, Any]
    created_at: str


class VideoTaskStatusResponse(BaseModel):
    task_id: str
    status: str
    progress: int = 0
    message: str
    result: Optional[Dict[str, Any]] = None
    created_at: str
    completed_at: Optional[str] = None


# Helper function to detect if text contains Chinese characters (保持不变)
def contains_chinese(text):
    """Check if the text contains Chinese characters"""
    return bool(re.search(u'[\u4e00-\u9fff]', text))


# Function to translate Chinese to English using DeepSeek API (保持不变)
async def translate_chinese_to_english(text):
    """Translate Chinese text to English using DeepSeek API"""
    # If text doesn't contain Chinese, return it as is
    if not contains_chinese(text):
        return text

    try:
        # Use DeepSeek API for translation
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
        }

        # Create a system prompt for translation
        system_prompt = "You are a professional translator. Translate the Chinese text to English accurately, preserving the meaning and context, especially for floral arrangement terminology."

        # Prepare the request payload
        payload = {
            "model": "deepseek-chat",
            "messages": [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": f"Translate this Chinese text to English: \"{text}\""}
            ],
            "temperature": 0.2,  # Low temperature for more consistent translation
            "max_tokens": 256
        }

        # Make API request
        logger.info(f"Translating Chinese text: {text}")
        api_response = requests.post(
            "http://10.2.8.77:3000/v1/chat/completions",
            headers=headers,
            json=payload
        )
        api_response.raise_for_status()

        # Extract the translation
        result = api_response.json()
        translation = result["choices"][0]["message"]["content"]

        # Clean up the translation (remove quotation marks or prefixes like "English translation:")
        translation = translation.strip('"\'')
        translation = re.sub(r'^(English translation:|Translated text:|Translation:)\s*', '', translation,
                             flags=re.IGNORECASE)
        translation = translation.strip()

        logger.info(f"Translated to English: {translation}")
        return translation

    except Exception as e:
        logger.error(f"Translation error: {str(e)}")
        # Return original text if translation fails
        return text


# Routes (大部分保持不变，只修改系统状态相关)
@app.get("/")
async def root():
    """Root endpoint"""
    return {"message": "Floral Art AI API is running (with Baidu Speech)"}


@app.post("/query", response_model=QueryResponse)
async def process_query(request: QueryRequest, background_tasks: BackgroundTasks):
    """处理关于插花艺术的文本查询"""
    # 这个函数保持完全不变
    try:
        # 处理查询
        response, source = floral_app.rag_system.process_query(request.query)

        result = {"response": response, "source": source}

        # 如果请求生成图像
        if request.generate_image:
            # 提取用于图像生成的提示词
            image_prompt = f"A floral arrangement featuring {request.query}"

            # 翻译中文查询到英文（如果需要）
            translated_query = await translate_chinese_to_english(request.query)

            # 调用文生图API
            try:
                # 增强提示词 - 使用翻译后的英文查询
                enhanced_prompt = f"A professional floral arrangement featuring {translated_query}, in professional style, with rich details, professional lighting, high quality photography"

                # 配置API请求
                api_url = "https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image"
                headers = {
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                    "Authorization": f"Bearer {TEXT_TO_IMAGE_API_KEY}"
                }

                # 准备请求参数
                payload = {
                    "text_prompts": [
                        {
                            "text": enhanced_prompt,
                            "weight": 1.0
                        }
                    ],
                    "cfg_scale": 9.0,
                    "height": 1024,
                    "width": 1024,
                    "samples": 1,
                    "steps": 30
                }

                # 发送API请求
                logger.info(f"发送文生图请求 (原始: {request.query}, 翻译: {translated_query})")
                logger.info(f"使用最终提示词: {enhanced_prompt}")
                api_response = requests.post(api_url, headers=headers, json=payload)
                api_response.raise_for_status()

                # 解析响应结果
                api_result = api_response.json()

                # API返回base64编码的图像
                if "artifacts" in api_result and len(api_result["artifacts"]) > 0:
                    # 提取base64数据
                    image_data = api_result["artifacts"][0]["base64"]

                    # 保存图像到文件
                    image_filename = f"floral_image_{int(time.time())}.png"
                    image_path = os.path.join("static", "images", image_filename)

                    # 确保目录存在
                    os.makedirs(os.path.dirname(image_path), exist_ok=True)

                    # 保存图像
                    with open(image_path, "wb") as f:
                        f.write(base64.b64decode(image_data))

                    # 返回图像URL
                    image_url = f"/static/images/{image_filename}"
                    logger.info(f"成功生成插花图像: {image_url}")

                    result["image_url"] = image_url
                else:
                    logger.error("API响应中没有生成图像")
                    result["image_url"] = "https://placeholder.com/floral_image.jpg"

            except Exception as img_error:
                # 如果图像生成失败，记录错误并使用占位符
                logger.error(f"图像生成失败: {str(img_error)}")
                result["image_url"] = "https://placeholder.com/floral_image.jpg"

        return result

    except Exception as e:
        logger.error(f"处理查询时出错: {str(e)}")
        raise HTTPException(status_code=500, detail=f"处理查询时出错: {str(e)}")


@app.post("/upload-knowledge")
async def upload_knowledge(file: UploadFile):
    """Upload a document to the knowledge base"""
    # 保持不变
    try:
        # Save the uploaded file
        file_path = f"temp/{file.filename}"
        os.makedirs("temp", exist_ok=True)

        with open(file_path, "wb") as f:
            content = await file.read()
            f.write(content)

        # Add to knowledge base
        floral_app.setup_knowledge_base([file_path])

        # Clean up temp file
        os.remove(file_path)

        return {"message": f"Successfully added {file.filename} to knowledge base"}

    except Exception as e:
        logger.error(f"Error uploading file: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error uploading file: {str(e)}")


@app.post("/transcribe-audio")
async def transcribe_audio(request: AudioTranscriptRequest):
    """Transcribe audio to text using Baidu speech recognition"""
    try:
        # Use our Baidu speech interaction manager
        speech_recognition_request = SpeechRecognitionRequest(
            audio_base64=request.audio_base64,
            dialect=request.dialect
        )

        # Process speech to text
        result = await speech_manager.process_speech_to_text(
            speech_recognition_request.audio_base64,
            speech_recognition_request.dialect
        )

        return {
            "transcription": result.transcription,
            "confidence": result.confidence,
            "dialect": result.dialect,
            "language_code": result.language_code
        }

    except Exception as e:
        logger.error(f"Error transcribing audio: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error transcribing audio: {str(e)}")


# 其他花艺相关功能保持不变...
def extract_flower_names(text: str) -> List[str]:
    """从查询文本中提取花卉名称"""
    # 简单版本：基于常见花名词列表匹配
    common_flowers = [
        "蒲公英", "玫瑰", "百合", "菊花", "康乃馨", "郁金香", "向日葵",
        "桂花", "牡丹", "荷花", "杜鹃", "茉莉", "兰花", "梅花"
    ]

    found_flowers = []
    for flower in common_flowers:
        if flower in text:
            found_flowers.append(flower)

    return found_flowers


async def translate_flower_name(flower_name: str) -> str:
    """专门用于翻译花卉名称的函数"""
    # 预定义的花卉名称映射(可以扩展这个字典)
    flower_translations = {
        "蒲公英": "dandelion (Taraxacum)",
        "玫瑰": "rose",
        "百合": "lily",
        "菊花": "chrysanthemum",
        "康乃馨": "carnation",
        "郁金香": "tulip",
        "向日葵": "sunflower",
        "桂花": "osmanthus",
        "牡丹": "peony",
        "荷花": "lotus",
        "杜鹃": "rhododendron",
        "茉莉": "jasmine",
        "兰花": "orchid",
        "梅花": "plum blossom"
    }

    # 如果在预定义映射中找到，直接返回
    if flower_name in flower_translations:
        return flower_translations[flower_name]

    # 否则使用通用翻译API
    return await translate_chinese_to_english(flower_name)


@app.post("/generate-image")
async def generate_floral_image(request: ImageGenerationRequest):
    """生成插花艺术图像"""
    # 保持不变
    try:
        # 检查并翻译中文提示词
        original_prompt = request.prompt
        translated_prompt = await translate_chinese_to_english(request.prompt)

        flower_names = extract_flower_names(original_prompt)

        translated_flowers = []
        for flower in flower_names:
            translated_flower = await translate_flower_name(flower)
            translated_flowers.append(translated_flower)

        flower_emphasis = ", ".join([f"with clearly visible {f}" for f in translated_flowers])

        enhanced_prompt = f"A professional floral arrangement {flower_emphasis}, {translated_prompt}, in {request.style} style, with rich details, professional lighting, high quality photography. The arrangement must prominently feature the mentioned flowers."

        # 使用您有权限访问的模型ID
        engine_id = "stable-diffusion-v1-6"

        # 配置API请求
        api_url = f"https://api.stability.ai/v1/generation/{engine_id}/text-to-image"

        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "Authorization": f"Bearer {TEXT_TO_IMAGE_API_KEY}"
        }

        # 简化请求参数，按照API文档格式
        payload = {
            "text_prompts": [
                {
                    "text": enhanced_prompt
                }
            ],
            "cfg_scale": 7,
            "height": 512,
            "width": 512,
            "samples": 1,
            "steps": 30
        }

        # 发送API请求
        logger.info(f"发送文生图请求 (原始: {original_prompt}, 翻译: {translated_prompt})")
        logger.info(f"使用最终提示词: {enhanced_prompt}")
        logger.info(f"使用模型: {engine_id}")
        response = requests.post(api_url, headers=headers, json=payload)

        if response.status_code != 200:
            logger.error(f"API请求返回状态码: {response.status_code}")
            logger.error(f"API错误响应: {response.text}")
            raise HTTPException(status_code=500, detail=f"图像生成API返回错误: {response.status_code}")

        # 解析响应结果
        result = response.json()

        # API返回的格式
        if "artifacts" in result and len(result["artifacts"]) > 0:
            # 提取base64数据
            image_data = result["artifacts"][0]["base64"]

            # 保存图像到文件
            image_filename = f"floral_image_{int(time.time())}.png"
            image_path = os.path.join("static", "images", image_filename)

            # 确保目录存在
            os.makedirs(os.path.dirname(image_path), exist_ok=True)

            # 保存图像
            with open(image_path, "wb") as f:
                f.write(base64.b64decode(image_data))

            # 返回图像URL
            image_url = f"/static/images/{image_filename}"
            logger.info(f"成功生成插花图像: {image_url}")

            return {
                "image_url": image_url,
                "original_prompt": original_prompt,
                "translated_prompt": translated_prompt,
                "enhanced_prompt": enhanced_prompt
            }
        else:
            logger.error("API响应中没有生成图像")
            raise HTTPException(status_code=500, detail="生成图像失败")

    except requests.exceptions.RequestException as e:
        logger.error(f"API请求失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"调用图像生成API错误: {str(e)}")
    except Exception as e:
        logger.error(f"生成图像时出错: {str(e)}")
        raise HTTPException(status_code=500, detail=f"生成图像时出错: {str(e)}")


@app.post("/train-local-model")
async def train_model(background_tasks: BackgroundTasks):
    """Start training the local model (async)"""
    try:
        # Start training in background
        background_tasks.add_task(floral_app.train_local_model)
        return {"message": "Local model training started in background"}

    except Exception as e:
        logger.error(f"Error starting model training: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Error starting model training: {str(e)}")


@app.get("/system-status")
async def system_status():
    """获取系统状态，包括百度语音服务状态"""
    try:
        # 检查百度ASR服务状态
        asr_available = {
            "baidu_asr": speech_manager.baidu_asr.is_available()
        }

        # 检查百度TTS服务状态
        tts_available = {
            "baidu_tts": speech_manager.baidu_tts.is_available(),
            "fallback_tts": speech_manager.fallback_tts.is_available()
        }

        return {
            "knowledge_base": {
                "document_count": 50,  # Placeholder - in real app, count documents
                "last_updated": "2023-04-11T12:00:00Z"
            },
            "local_model": {
                "available": floral_app.rag_system.local_model.is_available(),
                "model_path": floral_app.rag_system.local_model.model_path
            },
            "api_status": "active",
            "speech_interaction": {
                "asr_available": asr_available,
                "tts_available": tts_available,
                "supported_dialects": SUPPORTED_DIALECTS,
                "service_provider": "Baidu AI (百度AI)"
            },
            "text2video": {
                "available": True,
                "supported_styles": ["anime", "realistic", "painting"],
                "supported_languages": ["mandarin", "cantonese", "english"]
            },
            "baidu_services": {
                "asr_configured": bool(BAIDU_APP_ID and BAIDU_API_KEY and BAIDU_SECRET_KEY),
                "tts_configured": bool(BAIDU_APP_ID and BAIDU_API_KEY and BAIDU_SECRET_KEY),
                "app_id_preview": BAIDU_APP_ID[:8] + "..." if BAIDU_APP_ID else "未配置",
                "api_key_preview": BAIDU_API_KEY[:8] + "..." if BAIDU_API_KEY else "未配置"
            }
        }

    except Exception as e:
        logger.error(f"获取系统状态失败: {str(e)}")
        return {
            "error": f"获取系统状态失败: {str(e)}",
            "speech_interaction": {
                "asr_available": {"baidu_asr": False},
                "tts_available": {"baidu_tts": False, "fallback_tts": True},
                "supported_dialects": SUPPORTED_DIALECTS,
                "service_provider": "Baidu AI (百度AI)"
            }
        }


# New Speech Interaction Routes (修改为百度版本)
@app.post("/speech-to-text")
async def speech_to_text(request: SpeechRecognitionRequest):
    """Convert speech to text with dialect support using Baidu ASR"""
    try:
        result = await speech_manager.process_speech_to_text(
            request.audio_base64,
            request.dialect
        )

        return result

    except Exception as e:
        logger.error(f"Error in speech-to-text: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Speech recognition failed: {str(e)}")


@app.post("/speech-to-text-form")
async def speech_to_text_form(audio: UploadFile = File(...), dialect: str = Form("mandarin")):
    """处理表单提交的语音文件并转换为文本 - 百度版本"""
    try:
        # 读取上传的音频文件
        audio_content = await audio.read()

        # 转换为base64编码
        audio_base64 = base64.b64encode(audio_content).decode('utf-8')

        # 创建请求对象
        speech_recognition_request = SpeechRecognitionRequest(
            audio_base64=audio_base64,
            dialect=dialect
        )

        # 处理语音识别
        result = await speech_manager.process_speech_to_text(
            speech_recognition_request.audio_base64,
            speech_recognition_request.dialect
        )

        # 记录成功信息
        logger.info(f"百度语音识别成功: {result.transcription[:30]}...")

        return result

    except Exception as e:
        # 详细记录错误
        logger.error(f"百度语音识别失败: {str(e)}")
        logger.exception(e)  # 记录完整堆栈跟踪
        raise HTTPException(status_code=500, detail=f"百度语音识别失败: {str(e)}")


# 新增百度服务健康检查端点
@app.get("/baidu-status")
async def baidu_status():
    """检查百度语音服务的详细状态"""
    try:
        # 检查配置
        asr_configured = bool(BAIDU_APP_ID and BAIDU_API_KEY and BAIDU_SECRET_KEY and
                              BAIDU_APP_ID != "your_app_id" and
                              BAIDU_API_KEY != "your_api_key" and
                              BAIDU_SECRET_KEY != "your_secret_key")

        tts_configured = asr_configured  # TTS和ASR使用相同的配置

        return {
            "service_provider": "Baidu AI (百度智能云)",
            "asr_service": {
                "configured": asr_configured,
                "app_id_preview": BAIDU_APP_ID[:8] + "..." if BAIDU_APP_ID else "未配置",
                "available": speech_manager.baidu_asr.is_available(),
                "supported_languages": ["普通话", "粤语", "四川话", "英语"]
            },
            "tts_service": {
                "configured": tts_configured,
                "app_id_preview": BAIDU_APP_ID[:8] + "..." if BAIDU_APP_ID else "未配置",
                "available": speech_manager.baidu_tts.is_available(),
                "available_voices": speech_manager.get_available_voices()
            },
            "fallback_service": {
                "available": speech_manager.fallback_tts.is_available(),
                "type": "Simple beep tone generator"
            },
            "configuration_help": {
                "asr_setup": "在百度智能云控制台创建语音识别应用获取APP_ID、API_KEY和SECRET_KEY",
                "tts_setup": "在百度智能云控制台创建语音合成应用(可与ASR共用同一应用)",
                "console_url": "https://console.bce.baidu.com/"
            }
        }

    except Exception as e:
        logger.error(f"获取百度服务状态失败: {str(e)}")
        return {
            "error": f"获取百度服务状态失败: {str(e)}",
            "service_provider": "Baidu AI (百度智能云)",
            "status": "error"
        }


# 新增百度语音测试端点
@app.post("/test-baidu-voice")
async def test_baidu_voice():
    """测试百度语音服务连接"""
    try:
        # 测试TTS服务
        test_text = "这是百度语音合成服务的测试。"

        tts_result = await speech_manager.process_text_to_speech(
            test_text,
            dialect="mandarin"
        )

        tts_success = bool(tts_result.audio_base64)

        return {
            "tts_test": {
                "success": tts_success,
                "message": "TTS测试成功" if tts_success else "TTS测试失败",
                "audio_generated": tts_success,
                "duration": tts_result.duration if tts_success else 0
            },
            "asr_test": {
                "message": "ASR测试需要上传音频文件",
                "endpoint": "/speech-to-text-form"
            },
            "overall_status": "正常" if tts_success else "部分功能异常"
        }

    except Exception as e:
        logger.error(f"百度语音服务测试失败: {str(e)}")
        return {
            "error": f"测试失败: {str(e)}",
            "overall_status": "异常"
        }


@app.post("/text-to-speech")
async def text_to_speech(request: SpeechSynthesisRequest):
    """Convert text to speech with dialect support using Baidu TTS"""
    try:
        result = await speech_manager.process_text_to_speech(
            request.text,
            request.dialect,
            request.voice_id,
            request.speed
        )

        return result

    except Exception as e:
        logger.error(f"Error in text-to-speech: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Speech synthesis failed: {str(e)}")


@app.post("/detect-dialect")
async def detect_dialect(request: DialectDetectionRequest):
    """Detect dialect from audio using Baidu ASR"""
    try:
        result = await speech_manager.detect_dialect_from_audio(request.audio_base64)
        return {"dialects": result}

    except Exception as e:
        logger.error(f"Error in dialect detection: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Dialect detection failed: {str(e)}")


@app.get("/available-voices")
async def get_available_voices(dialect: Optional[str] = None):
    """Get available voices for TTS"""
    try:
        voices = speech_manager.get_available_voices(dialect)
        return {"voices": voices}

    except Exception as e:
        logger.error(f"Error getting available voices: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Failed to get voices: {str(e)}")


@app.post("/speech-query", response_model=QueryResponse)
async def process_speech_query(request: SpeechQueryRequest):
    """Process query from speech input and optionally return speech response using Baidu"""
    try:
        # Step 1: Convert speech to text
        speech_result = await speech_manager.process_speech_to_text(
            request.audio_base64,
            request.dialect
        )

        query_text = speech_result.transcription
        logger.info(f"Transcribed query: {query_text}")

        # Step 2: Process the query using RAG system
        response, source = floral_app.rag_system.process_query(query_text)

        result = {
            "response": response,
            "source": source,
            "transcription": query_text,
            "dialect": speech_result.dialect
        }

        # Step 3: Generate image if requested
        if request.generate_image:
            flower_names = extract_flower_names(query_text)
            translated_flowers = []
            for flower in flower_names:
                translated_flower = await translate_flower_name(flower)
                translated_flowers.append(translated_flower)

            # 构建增强提示词
            flower_emphasis = ", ".join([f"with clearly visible {f}" for f in translated_flowers])
            translated_query = await translate_chinese_to_english(query_text)

            enhanced_prompt = f"A professional floral arrangement {flower_emphasis}, {translated_query}, in professional style, with rich details, professional lighting, high quality photography. The arrangement must prominently feature the mentioned flowers."

            # Call StabilityAI API (simplified for brevity)
            try:
                # Configure API request
                api_url = "https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image"
                headers = {
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                    "Authorization": f"Bearer {TEXT_TO_IMAGE_API_KEY}"
                }

                payload = {
                    "text_prompts": [
                        {
                            "text": enhanced_prompt,
                            "weight": 1.0
                        }
                    ],
                    "cfg_scale": 7.0,
                    "height": 1024,
                    "width": 1024,
                    "samples": 1,
                    "steps": 30
                }

                api_response = requests.post(api_url, headers=headers, json=payload)
                api_response.raise_for_status()
                api_result = api_response.json()

                if "artifacts" in api_result and len(api_result["artifacts"]) > 0:
                    image_data = api_result["artifacts"][0]["base64"]
                    image_filename = f"floral_image_{int(time.time())}.png"
                    image_path = os.path.join("static", "images", image_filename)
                    os.makedirs(os.path.dirname(image_path), exist_ok=True)

                    with open(image_path, "wb") as f:
                        f.write(base64.b64decode(image_data))

                    image_url = f"/static/images/{image_filename}"
                    result["image_url"] = image_url

            except Exception as img_error:
                logger.error(f"Image generation failed: {str(img_error)}")

        # Step 4: Generate speech response if requested
        if request.voice_response:
            try:
                speech_synthesis_result = await speech_manager.process_text_to_speech(
                    response,
                    request.dialect,
                    request.voice_id
                )

                result["audio_response"] = speech_synthesis_result.audio_base64

            except Exception as speech_error:
                logger.error(f"Speech synthesis failed: {str(speech_error)}")

        return result

    except Exception as e:
        logger.error(f"Error processing speech query: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Processing speech query failed: {str(e)}")


# New Text-to-Video Endpoints
@app.post("/create-video", response_model=VideoTaskResponse)
async def create_video(request: CreateVideoRequest, background_tasks: BackgroundTasks):
    """Create a floral teaching video"""
    try:
        # Create a task ID
        task_id = f"task_{int(time.time())}_{uuid.uuid4().hex[:8]}"

        # Create task directory
        tasks_dir = os.path.join("static", "tasks")
        os.makedirs(tasks_dir, exist_ok=True)

        # Initialize task data
        task_data = {
            "id": task_id,
            "task_id": task_id,  # 添加这一行，保留原有id的同时增加task_id字段
            "status": "pending",
            "progress": 0,
            "message": "任务已创建，等待处理",
            "request": {
                "topic": request.topic,
                "character_style": request.character_style,
                "voice_id": request.voice_id,
                "style": request.style,
                "duration": request.duration,
                "language": request.language
            },
            "created_at": time.strftime("%Y-%m-%d %H:%M:%S"),
            "result": None
        }

        # Save task data
        task_path = os.path.join(tasks_dir, f"{task_id}.json")
        with open(task_path, 'w', encoding='utf-8') as f:
            json.dump(task_data, f, ensure_ascii=False, indent=2)

        # Convert to TextToVideoRequest
        video_request = TextToVideoRequest(
            topic=request.topic,
            character_style=request.character_style,
            voice_id=request.voice_id,
            style=request.style,
            duration=request.duration,
            language=request.language
        )

        # Start background task for video generation
        background_tasks.add_task(process_video_task, task_id, video_request)

        return task_data

    except Exception as e:
        logger.error(f"Error creating video task: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Video task creation failed: {str(e)}")


@app.get("/video-task/{task_id}", response_model=VideoTaskStatusResponse)
async def get_video_task(task_id: str):
    """Get video task status"""
    try:
        task_path = os.path.join("static", "tasks", f"{task_id}.json")

        if not os.path.exists(task_path):
            raise HTTPException(status_code=404, detail="Task not found")

        with open(task_path, 'r', encoding='utf-8') as f:
            task_data = json.load(f)

        return task_data

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting video task: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Failed to get video task: {str(e)}")


@app.get("/videos")
async def list_videos():
    """List all created videos"""
    try:
        videos = []
        videos_dir = os.path.join("static", "videos")

        if os.path.exists(videos_dir):
            for video_id in os.listdir(videos_dir):
                video_dir = os.path.join(videos_dir, video_id)
                if os.path.isdir(video_dir):
                    metadata_path = os.path.join(video_dir, "metadata.json")
                    if os.path.exists(metadata_path):
                        with open(metadata_path, 'r', encoding='utf-8') as f:
                            video_data = json.load(f)
                            videos.append(video_data)

        # Sort by creation time (newest first)
        videos.sort(key=lambda x: x.get('created_at', ''), reverse=True)

        return {"videos": videos, "count": len(videos)}

    except Exception as e:
        logger.error(f"Error listing videos: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Failed to list videos: {str(e)}")


@app.get("/video/{video_id}")
async def get_video(video_id: str):
    """Get video details"""
    try:
        video_dir = os.path.join("static", "videos", video_id)
        metadata_path = os.path.join(video_dir, "metadata.json")

        if not os.path.exists(metadata_path):
            raise HTTPException(status_code=404, detail="Video not found")

        with open(metadata_path, 'r', encoding='utf-8') as f:
            video_data = json.load(f)

        # Get script data if available
        script_data = None
        if 'script_id' in video_data:
            script_path = os.path.join("static", "temp", f"{video_data['script_id']}.json")
            if os.path.exists(script_path):
                with open(script_path, 'r', encoding='utf-8') as f:
                    script_data = json.load(f)

        return {
            "video": video_data,
            "script": script_data
        }

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error getting video details: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Failed to get video details: {str(e)}")


# Helper function for video task processing
async def process_video_task(task_id: str, request: TextToVideoRequest):
    """Process video generation task"""
    # Load task data
    task_path = os.path.join("static", "tasks", f"{task_id}.json")

    try:
        with open(task_path, 'r', encoding='utf-8') as f:
            task_data = json.load(f)

        # Update status to processing
        task_data["status"] = "processing"
        task_data["progress"] = 5
        task_data["message"] = "Starting video generation..."

        with open(task_path, 'w', encoding='utf-8') as f:
            json.dump(task_data, f, ensure_ascii=False, indent=2)

        # Generate video
        try:
            # Step 1: Generate script
            update_task_progress(task_id, 10, "Generating script...")

            # Step 2: Generate character
            update_task_progress(task_id, 30, "Creating virtual floral artist...")

            # Step 3: Generate voice
            update_task_progress(task_id, 50, "Synthesizing voice...")

            # Step 4: Generate character animation
            update_task_progress(task_id, 70, "Creating character animation...")

            # Step 5: Final video synthesis
            update_task_progress(task_id, 90, "Synthesizing final video...")

            # Run the actual video generation
            result = await video_generator.generate_video(request)

            # Update task with result
            with open(task_path, 'r', encoding='utf-8') as f:
                task_data = json.load(f)

            task_data["status"] = "completed"
            task_data["progress"] = 100
            task_data["message"] = "Video generation completed"
            task_data["result"] = result
            task_data["completed_at"] = time.strftime("%Y-%m-%d %H:%M:%S")

            with open(task_path, 'w', encoding='utf-8') as f:
                json.dump(task_data, f, ensure_ascii=False, indent=2)

        except Exception as gen_error:
            logger.error(f"Video generation failed: {str(gen_error)}")
            raise gen_error

    except Exception as e:
        # Update task with error
        try:
            with open(task_path, 'r', encoding='utf-8') as f:
                task_data = json.load(f)

            task_data["status"] = "failed"
            task_data["message"] = f"Video generation failed: {str(e)}"

            with open(task_path, 'w', encoding='utf-8') as f:
                json.dump(task_data, f, ensure_ascii=False, indent=2)

        except Exception as update_error:
            logger.error(f"Failed to update task status: {str(update_error)}")

        logger.error(f"Error processing video task: {str(e)}")


def update_task_progress(task_id: str, progress: int, message: str):
    """Update task progress"""
    try:
        task_path = os.path.join("static", "tasks", f"{task_id}.json")

        with open(task_path, 'r', encoding='utf-8') as f:
            task_data = json.load(f)

        task_data["progress"] = progress
        task_data["message"] = message

        with open(task_path, 'w', encoding='utf-8') as f:
            json.dump(task_data, f, ensure_ascii=False, indent=2)

    except Exception as e:
        logger.error(f"Failed to update task progress: {str(e)}")


# Helper functions
async def generate_image(prompt: str):
    """Background task to generate an image"""
    logger.info(f"Generating image for prompt: {prompt}")
    # Implementation would call your text-to-image API


@app.post("/generate-enhanced-image")
async def generate_enhanced_image(request: ImageGenerationRequest):
    """生成增强版花艺图像，包含多种变体"""
    try:
        logger.info(f"生成增强版图像: {request.prompt}")

        result = await enhanced_generator.generate_enhanced_image(request)

        return result

    except Exception as e:
        logger.error(f"增强图像生成失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"增强图像生成失败: {str(e)}")


@app.post("/edit-image-vase")
async def edit_image_vase(image_id: str, new_vase_style: str):
    """替换图像中的花瓶"""
    try:
        logger.info(f"替换花瓶: {image_id} -> {new_vase_style}")

        result = await interactive_editor.replace_vase(image_id, new_vase_style)

        if "error" in result:
            raise HTTPException(status_code=400, detail=result["error"])

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"花瓶替换失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"花瓶替换失败: {str(e)}")


@app.post("/edit-image-color")
async def edit_image_color(image_id: str, target_color: str):
    """改变图像中花朵的颜色"""
    try:
        logger.info(f"修改花朵颜色: {image_id} -> {target_color}")

        result = await interactive_editor.change_flower_color(image_id, target_color)

        if "error" in result:
            raise HTTPException(status_code=400, detail=result["error"])

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"颜色修改失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"颜色修改失败: {str(e)}")


@app.post("/edit-image-lighting")
async def edit_image_lighting(image_id: str, lighting_style: str):
    """增强图像光照效果"""
    try:
        logger.info(f"光照增强: {image_id} -> {lighting_style}")

        result = await interactive_editor.enhance_lighting(image_id, lighting_style)

        if "error" in result:
            raise HTTPException(status_code=400, detail=result["error"])

        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"光照增强失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"光照增强失败: {str(e)}")


@app.get("/image-metadata/{image_id}")
async def get_image_metadata(image_id: str):
    """获取图像元数据和变体信息"""
    try:
        metadata_path = os.path.join("static/temp", f"{image_id}_metadata.json")

        if not os.path.exists(metadata_path):
            raise HTTPException(status_code=404, detail="图像元数据不存在")

        with open(metadata_path, 'r', encoding='utf-8') as f:
            metadata = json.load(f)

        return metadata

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取图像元数据失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取元数据失败: {str(e)}")


@app.post("/batch-generate-styles")
async def batch_generate_styles(prompt: str, styles: List[str]):
    """批量生成不同风格的花艺图像"""
    try:
        logger.info(f"批量生成风格: {prompt} -> {styles}")

        results = []

        for style in styles:
            request = ImageGenerationRequest(
                prompt=prompt,
                style=style,
                composition="center",
                vase_style="modern",
                lighting="soft"
            )

            result = await enhanced_generator.generate_enhanced_image(request)

            if "error" not in result:
                results.append({
                    "style": style,
                    "image_id": result["image_id"],
                    "main_image": result["main_image"]
                })
            else:
                results.append({
                    "style": style,
                    "error": result["error"]
                })

        return {
            "prompt": prompt,
            "results": results,
            "generated_count": len([r for r in results if "error" not in r])
        }

    except Exception as e:
        logger.error(f"批量生成失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"批量生成失败: {str(e)}")


@app.post("/generate-composition-variants")
async def generate_composition_variants(prompt: str):
    """生成不同构图的花艺图像"""
    try:
        logger.info(f"生成构图变体: {prompt}")

        compositions = ["center", "left", "right", "asymmetric"]
        results = []

        for composition in compositions:
            request = ImageGenerationRequest(
                prompt=prompt,
                style="realistic",
                composition=composition,
                vase_style="modern",
                lighting="soft"
            )

            result = await enhanced_generator.generate_enhanced_image(request)

            if "error" not in result:
                results.append({
                    "composition": composition,
                    "image_id": result["image_id"],
                    "main_image": result["main_image"]
                })

        return {
            "prompt": prompt,
            "composition_variants": results
        }

    except Exception as e:
        logger.error(f"构图变体生成失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"构图变体生成失败: {str(e)}")


@app.post("/create-image-collection")
async def create_image_collection(
        prompt: str,
        collection_name: str,
        include_variants: bool = True
):
    """创建图像合集，包含多种风格和变体"""
    try:
        logger.info(f"创建图像合集: {collection_name}")

        # 基础配置组合
        configurations = [
            {"style": "realistic", "vase_style": "modern", "lighting": "soft"},
            {"style": "watercolor", "vase_style": "classic", "lighting": "natural"},
            {"style": "minimalist", "vase_style": "minimalist", "lighting": "studio"},
            {"style": "artistic", "vase_style": "vintage", "lighting": "dramatic"}
        ]

        collection_id = f"collection_{int(time.time())}_{uuid.uuid4().hex[:8]}"
        collection_images = []

        for i, config in enumerate(configurations):
            request = ImageGenerationRequest(
                prompt=prompt,
                style=config["style"],
                vase_style=config["vase_style"],
                lighting=config["lighting"],
                composition="center"
            )

            result = await enhanced_generator.generate_enhanced_image(request)

            if "error" not in result:
                collection_images.append({
                    "index": i,
                    "config": config,
                    "image_id": result["image_id"],
                    "main_image": result["main_image"],
                    "variants": result["variants"] if include_variants else []
                })

        # 保存合集元数据
        collection_metadata = {
            "id": collection_id,
            "name": collection_name,
            "prompt": prompt,
            "created_at": time.strftime("%Y-%m-%d %H:%M:%S"),
            "images": collection_images,
            "total_images": len(collection_images)
        }

        collection_path = os.path.join("static/temp", f"{collection_id}_collection.json")
        with open(collection_path, 'w', encoding='utf-8') as f:
            json.dump(collection_metadata, f, ensure_ascii=False, indent=2)

        return collection_metadata

    except Exception as e:
        logger.error(f"创建图像合集失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"创建合集失败: {str(e)}")


@app.get("/list-collections")
async def list_collections():
    """列出所有图像合集"""
    try:
        collections = []
        temp_dir = "static/temp"

        if os.path.exists(temp_dir):
            for filename in os.listdir(temp_dir):
                if filename.endswith("_collection.json"):
                    filepath = os.path.join(temp_dir, filename)
                    try:
                        with open(filepath, 'r', encoding='utf-8') as f:
                            collection_data = json.load(f)
                            collections.append({
                                "id": collection_data["id"],
                                "name": collection_data["name"],
                                "prompt": collection_data["prompt"],
                                "created_at": collection_data["created_at"],
                                "total_images": collection_data["total_images"]
                            })
                    except Exception as e:
                        logger.warning(f"读取合集文件失败: {filename}, {e}")

        # 按创建时间排序
        collections.sort(key=lambda x: x["created_at"], reverse=True)

        return {
            "collections": collections,
            "total_count": len(collections)
        }

    except Exception as e:
        logger.error(f"列出合集失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"列出合集失败: {str(e)}")


@app.get("/collection/{collection_id}")
async def get_collection(collection_id: str):
    """获取特定合集的详细信息"""
    try:
        collection_path = os.path.join("static/temp", f"{collection_id}_collection.json")

        if not os.path.exists(collection_path):
            raise HTTPException(status_code=404, detail="合集不存在")

        with open(collection_path, 'r', encoding='utf-8') as f:
            collection_data = json.load(f)

        return collection_data

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取合集失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取合集失败: {str(e)}")


# 辅助函数
def extract_image_id_from_url(image_url: str) -> str:
    """从图像URL中提取image_id"""
    # 假设URL格式为 /static/images/base_1234567890.png
    filename = os.path.basename(image_url)
    # 提取时间戳部分作为ID
    parts = filename.split('_')
    if len(parts) >= 2:
        return parts[1].split('.')[0]
    return filename.split('.')[0]


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)